﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Text;
using Thor.Domain;
using Thor.Domain.Configuration;

namespace Thor.Repository.EntFx
{
    public class CalendarRepository : RepositoryBase, ICalendarRepository
    {
        #region Constructors

        public CalendarRepository(Dictionary<string, object> repositoryParameters)
            : base(repositoryParameters) { }

        #endregion

        #region ICalendarRepository Members

        public void Insert(Calendar calendar)
        {
            if (calendar != null && Model != null)
            {
                var calendarEntity = CreateCalendarEntityFromPoco(calendar);
                Model.AddToCalendarEntities(calendarEntity);
                Model.SaveChanges();

                if (calendar.Appointments != null)
                {
                    foreach (var appointment in calendar.Appointments)
                    {
                        var appointmentEntity = CreateAppointmentEntityFromPoco(appointment, calendar.CalendarEmail);
                        Model.AddToAppointmentEntities(appointmentEntity);
                        Model.SaveChanges();
                    }
                }
            }
        }

        public void Update(Calendar calendar)
        {
            if (calendar != null && Model != null)
            {
                Delete(calendar);
                Insert(calendar);
            }
        }

        public void Delete(Calendar calendar)
        {
            if (calendar != null && Model != null)
            {
                var calendarEntity = Model.CalendarEntities.Where(c => c.Id == calendar.Id).FirstOrDefault();

                if (calendarEntity != null)
                {
                    var appointments = Model.AppointmentEntities.Where(a => a.CalendarId == calendarEntity.CalendarEmail).ToList();

                    if (appointments != null)
                    {
                        foreach (var appointment in appointments)
                        {
                            Model.DeleteObject(appointment);
                            Model.SaveChanges();
                        }
                    }

                    Model.DeleteObject(calendarEntity);
                    Model.SaveChanges();
                }
            }
        }

        public List<Calendar> Fetch()
        {
            if (Model != null)
            {
                List<Calendar> result = new List<Calendar>();

                var calendarEntities = Model.CalendarEntities.ToList();

                if (calendarEntities != null)
                {
                    foreach (var calendarEntity in calendarEntities)
                    {
                        Calendar calendar = CreateCalendarFromEntity(calendarEntity);
                        calendar.Appointments = new List<Appointment>();

                        var appointmentEntities = Model.AppointmentEntities.Where(a => a.CalendarId == calendar.CalendarEmail).ToList();

                        if (appointmentEntities != null)
                        {
                            foreach (var appointmentEntity in appointmentEntities)
                                calendar.Appointments.Add(CreateAppointmentFromEntity(appointmentEntity));
                        }

                        result.Add(calendar);
                    }
                }

                return result;
            }

            return null;
        }

        public Calendar Fetch(Guid id)
        {
            if (Model != null)
            {
                var calendarEntity = Model.CalendarEntities.Where(c => c.Id == id).FirstOrDefault();

                if (calendarEntity != null)
                {
                    Calendar calendar = CreateCalendarFromEntity(calendarEntity);
                    calendar.Appointments = new List<Appointment>();

                    var appointmentEntities = Model.AppointmentEntities.Where(a => a.CalendarId == calendar.CalendarEmail).ToList();

                    if (appointmentEntities != null)
                    {
                        foreach (var appointmentEntity in appointmentEntities)
                            calendar.Appointments.Add(CreateAppointmentFromEntity(appointmentEntity));
                    }

                    return calendar;
                }
                else
                    return null;
            }

            return null;
        }

        #endregion

        #region Methods

        private CalendarEntity CreateCalendarEntityFromPoco(Calendar poco)
        {
            CalendarEntity entity = new CalendarEntity();

            entity.Alias = poco.Alias;
            entity.ApplicationName = this.ApplicationName;
            entity.CalendarEmail = poco.CalendarEmail;
            entity.DisplaySubject = poco.DisplaySubject;
            entity.EndTime = poco.EndTime;
            entity.Id = poco.Id;
            entity.PublicCanBook = poco.PublicCanBook;
            entity.PublicCanView = poco.PublicCanView;
            entity.StartTime = poco.StartTime;
            entity.TimeZone = poco.TimeZone;
            entity.UseBookingAgent = poco.UseBookingAgent;
            entity.UseTimeframe = poco.UseTimeframe;

            return entity;
        }

        private Calendar CreateCalendarFromEntity(CalendarEntity entity)
        {
            Calendar poco = new Calendar();

            poco.Alias = entity.Alias;
            poco.CalendarEmail = entity.CalendarEmail;
            poco.DisplaySubject = entity.DisplaySubject;
            poco.EndTime = entity.EndTime;
            poco.Id = entity.Id;
            poco.PublicCanBook = entity.PublicCanBook;
            poco.PublicCanView = entity.PublicCanView;
            poco.StartTime = entity.StartTime;
            poco.TimeZone = entity.TimeZone;
            poco.UseBookingAgent = entity.UseBookingAgent;
            poco.UseTimeframe = entity.UseTimeframe;

            return poco;
        }

        private AppointmentEntity CreateAppointmentEntityFromPoco(Appointment poco, string calendarId)
        {
            AppointmentEntity entity = new AppointmentEntity();

            entity.ApplicationName = ApplicationName;
            entity.CalendarId = calendarId;
            entity.EndTime = poco.EndTime;
            entity.Id = poco.Id;
            entity.StartTime = poco.StartTime;
            entity.Subject = poco.Subject;

            return entity;
        }

        private Appointment CreateAppointmentFromEntity(AppointmentEntity entity)
        {
            Appointment poco = new Appointment();

            poco.EndTime = entity.EndTime;
            poco.Id = entity.Id;
            poco.StartTime = entity.StartTime;
            poco.Subject = entity.Subject;

            return poco;
        }

        #endregion
    }
}
